<template>
  <div>
    <search-form
          v-watermark="{text: email,time:Date.now()}"
          :has-back-btn="hasBackBtn"
           @folding = "setTableLayout"
            v-if="formOptions.forms.length"
            ref="searchForm"
            :expand="expand"
            :autoHeight="autoHeight"
            :forms="formOptions.forms"
            :size="formOptions.size"
            :fuzzy="formOptions.fuzzy"
            :inline="formOptions.inline"
            :label-width="formOptions.labelWidth"
            :item-width="formOptions.itemWidth"
            :submit-handler="searchHandler"
            :submit-loading="loading"
            :showSearchBtn="formOptions.showSearchBtn"
            :showResetBtn="formOptions.showResetBtn"
            :submitBtnText="formOptions.submitBtnText"
            :resetBtnText="formOptions.resetBtnText"
            :resetBtnCallback="formOptions.resetBtnCallback">
      <template slot="backBtn">
        <slot name="backBtn"></slot>
      </template>
      <template slot="download">
          <slot name="customerBtn"></slot>
      </template>
      <template slot="formButton">
        <slot name="button"></slot>
      </template>
      <template slot="form">
        <slot name="form-custom" :loading="loading" :search="searchHandler" />
      </template>
    </search-form>
    <slot />
    <div class="search-table-info" v-if="showOperatingButton">
      <div class="search-table-info-btns" style="display: flex;justify-content: space-between;align-items: center;width: 100%">
        <slot name="button"></slot>
        <!--<el-divider direction="vertical" />
        <i class="el-icon-refresh-right" @click="fetchHandler"></i>
        <i class="el-icon-setting"></i>
        <i class="el-icon-full-screen"></i>-->
      </div>
    </div>
    <el-table v-loading.lock="loading"
              v-watermark="{text: email,time:Date.now()}"
              :tree-props="treeOptions"
              class="search-table-main"
              ref="table"
              :data="tableData"
              :border="border"
              :size="size"
              :stripe="stripe"
              v-el-height-adaptive-table="adaptive"
              :height="height"
              :max-height="maxHeight"
              :fit="fit"
              :show-header="showHeader"
              :highlight-current-row="highlightCurrentRow"
              :current-row-key="currentRowKey"
              :row-class-name="rowClassName"
              :row-style="rowStyle"
              :row-key="rowKey"
              :empty-text="emptyText"
              :default-expand-all="defaultExpandAll"
              :expand-row-keys="expandRowKeys"
              :default-sort="defaultSort"
              :tooltip-effect="tooltipEffect"
              :show-summary="showSummary"
              :sum-text="sumText"
              :summary-method="summaryMethod"
              :style="tableStyle"
              @select="(selection, row) => emitEventHandler('select', selection, row)"
              @select-all="selection => emitEventHandler('select-all', selection)"
              @selection-change="selection => emitEventHandler('selection-change', selection)"
              @cell-mouse-enter="(row, column, cell, event) => emitEventHandler('cell-mouse-enter', row, column, cell, event)"
              @cell-mouse-leave="(row, column, cell, event) => emitEventHandler('cell-mouse-leave', row, column, cell, event)"
              @cell-click="(row, column, cell, event) => emitEventHandler('cell-click', row, column, cell, event)"
              @cell-dblclick="(row, column, cell, event) => emitEventHandler('cell-dblclick', row, column, cell, event)"
              @row-click="(row, event, column) => emitEventHandler('row-click', row, event, column)"
              @row-dblclick="(row, event) => emitEventHandler('row-dblclick', row, event)"
              @row-contextmenu="(row, event) => emitEventHandler('row-contextmenu', row, event)"
              @header-click="(column, event) => emitEventHandler('header-click', column, event)"
              @sort-change="args => emitEventHandler('sort-change', args)"
              @filter-change="filters => emitEventHandler('filter-change', filters)"
              @current-change="(currentRow, oldCurrentRow) => emitEventHandler('current-change', currentRow, oldCurrentRow)"
              @header-dragend="(newWidth, oldWidth, column, event) => emitEventHandler('header-dragend', newWidth, oldWidth, column, event)"
              @expand-change="(row, expanded) => emitEventHandler('expand-change', row, expanded)" >

      <slot name="prepend" />

      <template v-for="(column, columnIndex) in columns">
        <el-table-column
                :key="columnIndex"
                :column-key="column.columnKey"
                :prop="column.prop"
                :label="column.label"
                :width="column.minWidth ? '-' : (column.width || 'auto')"
                :minWidth="column.minWidth || column.width || '140'"
                :fixed="column.fixed"
                :render-header="column.renderHeader"
                :sortable="column.sortable"
                :sort-by="column.sortBy"
                :sort-method="column.method"
                :resizable="column.resizable"
                :formatter="column.formatter"
                :show-overflow-tooltip="column.showOverflowTooltip"
                :align="column.align"
                :header-align="column.headerAlign || column.align"
                :class-name="column.className"
                :label-class-name="column.labelClassName"
                :selectable="column.selectable"
                :reserve-selection="column.reserveSelection"
                :filters="column.filters"
                :filter-placement="column.filterPlacement"
                :filter-multiple="column.filterMultiple"
                :filter-method="column.filterMethod"
                :filtered-value="column.filteredValue"
                v-if="column.type === undefined">
          <template slot-scope="scope" :scope="newSlotScope ? 'scope' : false">
            <span v-if="column.filter">
              {{ Vue.filter(column['filter'])(scope.row[column.prop]) }}
            </span>
            <span v-else-if="column.slotName">
              <slot :name="column.slotName" :row="scope.row" :$index="scope.$index" />
            </span>
            <span v-else-if="column.render">
              {{ column.render(scope.row) }}
            </span>
            <span v-else-if="column.formatter">
              {{ column.formatter(scope.row, scope.column, scope.row[column.prop], scope.$index) }}
            </span>
            <span v-else>
              {{ scope.row[column.prop] }}
            </span>
          </template>
        </el-table-column>
        <el-table-column v-bind="column" :key="columnIndex" v-else></el-table-column>
      </template>
      <slot name="append" />
    </el-table>
    <div v-if="showPagination"
         style="text-align: right;background: #fff;padding: 10px">
      <el-pagination
              background
              :hide-on-single-page=false
              @size-change="handleSizeChange"
              @current-change="handleCurrentChange"
              :current-page="pagination.pageIndex"
              :page-sizes="pageSizes"
              :page-size="pagination.pageSize"
              :layout="paginationLayout"
              :total="total">
      </el-pagination>
    </div>
  </div>
</template>

<script>
import elHeightAdaptiveTable from '@/directives/el-table';
import searchForm from './search-form';
import {mapGetters} from 'vuex';
export default {
    name: 'Tablepagination',
    components: {
        searchForm
    },
    directives: {
        elHeightAdaptiveTable
    },
    props: {
        expand: {
            type: Boolean,
            default: false
        },
        treeOptions: {
            type: Object,
            default: () => {
                return {'children': 'childrenList', 'hasChildren': 'hasChildren'};
            }
        },
        showOperatingButton: {
            type: Boolean,
            default: true
        },
        autoHeight: {
            type: Boolean,
            default: false
        },
        fixedHeader: {
            type: Boolean,
            default: false
        },
        adaptive: {
            type: Object,
            default: () => {
                return {fixedHeader: false};
            }
        },
        height: [String, Number],
        maxHeight: [String, Number],
        size: String,
        stripe: {
            type: Boolean,
            default: true
        },
        border: {
            type: Boolean,
            default: true
        },
        fit: {
            type: Boolean,
            default: true
        },
        showHeader: {
            type: Boolean,
            default: true
        },
        highlightCurrentRow: Boolean,
        currentRowKey: [String, Number],
        rowClassName: [String, Function],
        rowStyle: [String, Function],
        rowKey: {
            type: [String, Function],
            default: 'id'
        },
        emptyText: String,
        defaultExpandAll: {
            type: Boolean,
            default: false
        },
        expandRowKeys: Array,
        defaultSort: Object,
        tooltipEffect: String,
        showSummary: Boolean,
        sumText: String,
        summaryMethod: Function,
        // custom attributes
        tableStyle: {
            type: String,
            default: 'width:100%;margin-top:0px;'
        },
        fetch: {
            type: Function
        },
        url: {
            type: String
        },
        method: {
            type: String,
            default: 'get',
            validator: value => {
                const methodTypes = ['get', 'post', 'put', 'delete'];
                return methodTypes.indexOf(value.toLowerCase()) !== -1;
            }
        },
        headers: {
            type: Object,
            default: () => {
                return {};
            }
        },
        listField: {
            type: String,
            default: 'data.list'
        },
        totalField: {
            type: String,
            default: 'data.total'
        },
        params: {
            type: Object,
            default: () => {
                return {};
            }
        },
        formOptions: {
            type: Object
        },
        autoLoad: {
            type: Boolean,
            default: true
        },
        type: {
            type: String,
            default: 'remote',
            validator (value) {
                const types = ['remote', 'local'];
                const validType = types.indexOf(value) !== -1;
                if (!validType) {
                    throw new Error(`Invalid type of '${value}', please set one type of 'remote' or 'local'.`);
                }
                return validType;
            }
        },
        data: {
            type: Array
        },
        dataHandler: {
            type: Function
        },
        columns: {
            type: Array,
            required: true
        },
        showPagination: {
            type: Boolean,
            default: true
        },
        pageSizes: {
            type: Array,
            default: () => {
                return [20, 50, 100];
            }
        },
        paginationLayout: {
            type: String,
            default: 'total, sizes, prev, pager, next, jumper'
        },
        pageIndexKey: {
            type: String,
            default: 'pageIndex'
        },
        pageSizeKey: {
            type: String,
            default: 'pageSize'
        },
        hasBackBtn: {
            type: Boolean,
            default: false
        }
    },
    data () {
        return {
            pagination: {
                pageIndex: 1,
                pageSize: (() => {
                    const { pageSizes } = this;
                    if (pageSizes.length > 0) {
                        return pageSizes[0];
                    }
                    return 20;
                })()
            },
            total: 0,
            loading: false,
            tableData: [],
            cacheLocalData: []
        };
    },
    computed: {
        newSlotScope () {
            return Number(Vue.version.replace(/\./g, '')) >= 250;
        },
        ...mapGetters(['email'])
    },
    methods: {
        handleSizeChange (size) {
            this.pagination.pageSize = size;
            this.dataChangeHandler();
        },
        handleCurrentChange (pageIndex) {
            this.pagination.pageIndex = pageIndex;
            this.dataChangeHandler();
        },
        resetFields () {
            this.$refs['searchForm'].resetFields();
        },
        searchHandler (resetPageIndex = true) {
            if (resetPageIndex) {
                this.pagination.pageIndex = 1;
            }
            this.dataChangeHandler(arguments[0]);
        },
        dataChangeHandler () {
            const { type } = this;
            if (type === 'local') {
                this.dataFilterHandler(arguments[0]);
            } else if (type === 'remote') {
                this.fetchHandler(arguments[0]);
            }
        },
        dataFilter (data) {
            const { pageIndex, pageSize } = this.pagination;
            return data.filter((v, i) => {
                return i >= (pageIndex - 1) * pageSize && i < pageIndex * pageSize;
            });
        },
        dataFilterHandler (formParams) {
            const { cacheLocalData, params, pagination } = this;
            const { pageIndex, pageSize } = pagination;
            const mergeParams = Object.assign(params, formParams);
            const validParamKeys = Object.keys(mergeParams).filter(v => {
                return mergeParams[v] !== undefined && mergeParams[v] !== '';
            });
            const searchForm = this.$refs['searchForm'];
            let paramFuzzy;
            if (searchForm) {
                paramFuzzy = searchForm.getParamFuzzy();
            }
            if (validParamKeys.length > 0) {
                const validData = cacheLocalData.filter(v => {
                    let valids = [];
                    validParamKeys.forEach(vv => {
                        if (typeof v[vv] === 'number') {
                            valids.push(
                                paramFuzzy && paramFuzzy[vv] ? (String(v[vv]).indexOf(String(mergeParams[vv])) !== -1)
                                    : (String(v[vv]) === String(mergeParams[vv]))
                            );
                        } else {
                            valids.push(
                                paramFuzzy && paramFuzzy[vv] ? (v[vv].indexOf(mergeParams[vv]) !== -1) : (v[vv] === mergeParams[vv])
                            );
                        }
                    });
                    return valids.every(vvv => {
                        return vvv;
                    });
                });
                this.tableData = this.dataFilter(validData);
                this.total = validData.length;
            } else {
                this.total = cacheLocalData.length;
                this.tableData = this.dataFilter(cacheLocalData);
            }
        },
        fetchHandler (formParams = {}, noCase = true) {
            this.loading = true;
            let { fetch, method, url, $axios, headers,
                listField, pageIndexKey, pageSizeKey,
                totalField, params, showPagination,
                pagination } = this;
            params = JSON.parse(JSON.stringify(Object.assign(params, formParams)));
            if (showPagination && noCase) {
                params = Object.assign(params, {
                    [pageIndexKey]: pagination.pageIndex,
                    [pageSizeKey]: pagination.pageSize
                });
            } else {
                this.$nextTick(() => {
                    this.pagination.pageIndex = 1;
                });
            }
            let requestObject = null;
            if (fetch) {
                requestObject = fetch(params);
            } else {
                $axios.interceptors.request.use(
                    config => {
                        Object.keys(headers).forEach(v => {
                            config.headers[v] = headers[v];
                        });
                        return config;
                    },
                    error => {
                        return Promise.reject(error);
                    }
                );
                method = method.toLowerCase();
                if (method === 'get') {
                    requestObject = $axios[method](url, { params });
                } else {
                    requestObject = $axios[method](url, params);
                }
            }
            requestObject.then(response => {
                let result = response;
                if (response && !(response instanceof Array)) {
                    if (listField && listField.indexOf('.') !== -1) {
                        listField.split('.').forEach(vv => {
                            result = result[vv];
                        });
                    } else {
                        result = response[listField];
                    }
                }
                if (!result || !(result instanceof Array)) {
                    this.loading = false;
                    throw new Error(`The result of key:${listField} is not Array.`);
                    // return false;
                }
                if (this.dataHandler) {
                    this.tableData = result.map(this.dataHandler);
                } else {
                    this.tableData = result;
                }
                let totalValue = response;
                if (Object.prototype.toString.call(response) === '[object Array]') {
                    totalValue = response.length;
                } else if (typeof response === 'object') {
                    if (totalField && totalField.indexOf('.') !== -1) {
                        totalField.split('.').forEach(vv => {
                            totalValue = totalValue[vv];
                        });
                    } else {
                        totalValue = response[totalField];
                    }
                } else {
                    totalValue = 0;
                }
                this.total = totalValue;
                this.loading = false;
            }).catch(error => {
                console.error('Get remote data failed. ', error);
                this.loading = false;
            });
        },
        emitEventHandler (event) {
            this.$emit(event, ...Array.from(arguments).slice(1));
        },
        loadLocalData (data) {
            const { autoLoad } = this;
            if (!data) {
                this.showPagination = false;
                throw new Error('When the type is \'local\', you must set attribute \'data\' and \'data\' must be a array.');
                // return false;
            }
            const cacheData = JSON.parse(JSON.stringify(data));
            this.cacheLocalData = cacheData;
            if (autoLoad) {
                this.tableData = this.dataFilter(cacheData);
                this.total = cacheData.length;
            }
        },
        toggleRowSelection (row) {
            this.$nextTick(() => {
                const i = this.tableData.findIndex(res => res.spuId === row.spuId);
                this.$refs.table.toggleRowSelection(this.tableData[i], true);
            });
        },
        setCurrentRow (row) {
            this.$refs.table.setCurrentRow(row);
        },
        setTableLayout (event) {
            setTimeout(() => {
                const bottomOffset = (this.adaptive && this.adaptive.bottomOffset) || 66;
                let height = window.innerHeight - this.$refs.table.$el.getBoundingClientRect().top - bottomOffset;
                this.$refs.table.layout.setHeight(height);
                this.$refs.table.doLayout();
            }, 400);
        },
        doLayout () {
            this.$refs.table.doLayout();
        }
    },
    mounted () {
        this.$refs['table'].$on('expand', (row, expanded) => this.emitEventHandler('expand', row, expanded));
        const { type, autoLoad, data, formOptions, params } = this;
        if (type === 'remote' && autoLoad) {
            if (formOptions.forms.length) {
                this.$refs['searchForm'].getParams((error, formParams) => {
                    if (!error) {
                        this.fetchHandler(Object.assign(formParams, params));
                    }
                });
            } else {
                this.fetchHandler(params);
            }
        } else if (type === 'local') {
            this.loadLocalData(data);
        }
    },
    watch: {
        data: function (value) {
            this.loadLocalData(value);
        }
    }
};
</script>

<style scoped lang="scss">
.search-table-info{
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 64px;
  background: #fff;
  margin-top: 12px;
  padding: 10px 34px 10px;
}
</style>

<style lang="scss">
.search-table-main{
  &.el-table td{
    //   border: none;
  }
  .el-table__fixed, .el-table__fixed-right{
    border-bottom: 1px solid #ebeef5;
    background: #fff;
    // border: none;
  }
  .el-table__fixed-right:before, .el-table__fixed:before{
    display: none;
    // border: none;
  }
}
.el-table--enable-row-transition .el-table__body td {
    -webkit-transition: background-color .25s ease;
    transition: background-color .25s ease;
    border: none;
    padding: 0;
}
.el-table {
    width: 100%;
    // max-width: 100%;
    font-size: 14px;
    color: #606266;
    // padding: 0 20px;
}
</style>
